//=============================================================================

#include <fstream>
#include "../inc/aObject.h"

//=============================================================================

const long objMagico = (~777);

//=============================================================================

using namespace std;

//=============================================================================

aObject::aObject(unsigned long setId) : id(setId)
{
  name = "object";
  health = 100;
  mana = 100;
  stamina = 0;
}

//=============================================================================

void aObject::aoSetDrawProperties(unsigned char params)
{
  mainModel.draw = ((params & DRAW) != 0);
  mainModel.drawTriangles = ((params & DRAW_TRIANGLES) != 0);
  mainModel.drawLines = ((params & DRAW_LINES) != 0);
  mainModel.drawPoints = ((params & DRAW_POINTS) != 0);
  mainModel.drawNormals = ((params & DRAW_NORMALS) != 0);
  mainModel.drawSkeleton = ((params & DRAW_SKELETON) != 0);
  mainModel.drawOrigin = ((params & DRAW_ORIGIN) != 0);
  mainModel.drawJointsAxis = ((params & DRAW_JOINTS_AXIS) != 0);
}

//=============================================================================

aotRet aObject::aoLoadObject(const aString& path)
{
  if (path.asGetLength() <= 0)
    return OBJ_BAD_PATH;

  fstream file;

  file.open(path.asGetString(), ios_base::in | ios_base::binary);

  if (!file.is_open())
    return OBJ_CANT_OPEN_OBJECT_FILE;

  //read the header;
  long magicNumber = 0;
  size_t nameLength;

  file.read((char*)&magicNumber, sizeof(magicNumber));

  if (magicNumber != objMagico)
    return OBJ_BAD_MAGIC_IN_OBJECT_FILE;

  aoClearObjectData();

  file.read((char*)&nameLength, sizeof(size_t));

  wchar_t* namePtr = new wchar_t[nameLength + 1];
  const int headerCounter = 4;
  int counts[headerCounter];// 0 - vertexes
                            // 1 - textures
                            // 2 - joints
                            // 3 - animations

  size_t volumes[headerCounter];// 0 - surface volume
                                // 1 - skin volume
                                // 2 - skeleton volume
                                // 3 - anim volume

  file.read((char*)namePtr, nameLength*name.asGetCharSize());
  namePtr[nameLength] = 0;
  name = namePtr;

  file.read((char*)&health, sizeof(int));
  file.read((char*)&mana, sizeof(int));
  file.read((char*)&stamina, sizeof(int));

  file.read((char*)counts, sizeof(int)*headerCounter);
  file.read((char*)volumes, sizeof(size_t)*headerCounter);

  char* vertexesData = new char[volumes[0]];

  file.read((char*)vertexesData, volumes[0]);

  switch(mainModel.asAbsorbSurfaceData(vertexesData, counts[0]))
  {
    case SURF_ABS_BAD_DATA_POINTER:
    {
      delete [] namePtr;
      delete [] vertexesData;

      file.close();

      return OBJ_SURFACE_ABS_BAD_DATA_POINTER;
    }
    case SURF_ABS_BAD_VERTEXES_COUNT:
    {
      delete [] namePtr;
      delete [] vertexesData;

      file.close();

      return OBJ_SURFACE_ABS_BAD_VERTEXES_COUNT;
    }
    default:
    {
      break;
    }
  }

  char* texData = new char[volumes[1]];

  file.read((char*)texData, volumes[1]);

  switch(mainModel.asAbsorbSkinData(texData, counts[1]))
  {
    case ABS_BAD_SKIN_DATA_POINTER:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;

      file.close();

      return OBJ_SKIN_ABS_BAD_DATA_POINTER;
    }
    case ABS_BAD_TEXTURES_COUNT:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;

      file.close();

      return OBJ_SKIN_ABS_BAD_TEXTURES_COUNT;
    }
    default:
    {
      break;
    }
  }

  char* jointsData = new char[volumes[2]];

  file.read((char*)jointsData, volumes[2]);

  switch(mainModel.amAbsorbSkeletonData(jointsData, counts[2]))
  {
    case ABS_BAD_SKELETON_DATA_POINTER:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;
      delete [] jointsData;

      file.close();

      return OBJ_SKELETON_ABS_BAD_DATA_POINTER;
    }
    case ABS_BAD_SKELETON_JOINTS_COUNT:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;
      delete [] jointsData;

      file.close();

      return OBJ_SKELETON_ABS_BAD_JOINTS_COUNT;
    }
    default:
    {
      break;
    }
  }

  char* animData = new char[volumes[3]];

  file.read((char*)animData, volumes[3]);

  switch(mainModel.amAbsorbAnimationData(animData))
  {
    case ABS_BAD_ANIM_DATA_POINTER:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;
      delete [] jointsData;
      delete [] animData;

      file.close();

      return OBJ_ANIM_ABS_BAD_DATA_POINTER;
    }
    case ABS_NO_SUCH_JOINT_FOR_ANIM:
    {
      delete [] namePtr;
      delete [] vertexesData;
      delete [] texData;
      delete [] jointsData;
      delete [] animData;

      file.close();

      return OBJ_ANIM_ABS_NO_SUCH_JOINT_FOR_ANIM;
    }
    default:
    {
      break;
    }
  }

  delete [] namePtr;
  delete [] vertexesData;
  delete [] texData;
  delete [] jointsData;
  delete [] animData;
  
  file.close();

  return OBJ_DONE;
}

//=============================================================================

void aObject::aoGetMainModelAnimationsList(aList<aString>& animList)
{
  animList.alRemoveItems();

  aItem<aString>* tmpItem = mainModel.hasAnimations.alGetFirstItem();
  
  while(tmpItem)
  {
    animList.alAddItem()->data = tmpItem->data;

    tmpItem = tmpItem->next;
  }
}

//=============================================================================

bool aObject::aoFindAction(aanAct type)
{
  aItem<aAction>* tmpAction = actions.alGetFirstItem();

  while(tmpAction)
  {
    if (tmpAction->data.aaGetType() == type)
      break;

    tmpAction = tmpAction->next;
  }

  if (tmpAction)
    return 1;

  return 0;
}

//=============================================================================

aObject::~aObject()
{
}

//=============================================================================
